package com.lucas.lai.state.machine.squirrel.sample.one;

/**
 * @author lucas.lai
 * @date 2023/11/9
 */

import com.lucas.lai.state.machine.squirrel.sample.one.context.OrderContext;
import com.lucas.lai.state.machine.squirrel.sample.one.envent.OrderEvent;
import com.lucas.lai.state.machine.squirrel.sample.one.envent.OrderStatusEventListener;
import com.lucas.lai.state.machine.squirrel.sample.one.machine.OrderStateMachine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.squirrelframework.foundation.fsm.StateMachineBuilderFactory;
import org.squirrelframework.foundation.fsm.StateMachineConfiguration;
import org.squirrelframework.foundation.fsm.UntypedStateMachine;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;

/**
 * 创建无类型化状态机
 * 通过Spring创建StateMachineBuilder实例，通过buidler创建状态机(单例)
 * 注: 若有两个不同的业务状态机，它们的状态和事件都不同，那么不能使用同一个StateMachineBuilder实例来创建状态机
 * @author lucas
 */
@Slf4j
public class StateMachineEngine<T extends UntypedStateMachine> implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    protected UntypedStateMachineBuilder orderStateMachineBuilder = null;

    @SuppressWarnings("unchecked")
    public StateMachineEngine() {
        orderStateMachineBuilder = StateMachineBuilderFactory.create(OrderStateMachine.class, ApplicationContext.class);
    }


    //注入applicationContext，并在创建StateMachine实例时注入
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 可以通过向OrderContext 上下文传递一些业务参数，比如orderId等等
     */
    public void fire(OrderEvent event, OrderContext context) {
        //创建状态机StateMachine
        OrderStateMachine stateMachine = orderStateMachineBuilder.newUntypedStateMachine(
                context.orderDTO.getState(),
                //可打印debug详细日志
                StateMachineConfiguration.create().enableDebugMode(false).enableAutoStart(true),
                //注入applicationContext
                applicationContext);
        //stateMachine.addDeclarativeListener(new OrderStatusEventListener());
        stateMachine.fire(event, context);
        log.info("fire调用完成....执行事件{}",event);
    }
}
